/***************************************************/
//Basic Matrix Class
//Code By Lys
//2015.09.16
/***************************************************/

#include <ios>
#include <vector>

class Matrix
{
	//friend function declare
	friend Matrix operator*(double, Matrix);

public:
	//construct functions(3 reload)
	Matrix();					
	Matrix(unsigned int row, unsigned int col = 0);
	Matrix(Matrix&);			

	//basic IO functions
	void resetDim(unsigned int row, unsigned int col = 0);
	void resetAsIdentity(unsigned int dim);
	void insertData(unsigned int row, std::vector<double> data);
	inline double getVal(unsigned int row, unsigned int col);
	inline unsigned int getRow();
	inline unsigned int getCol();

	//math operator reload
	Matrix &operator=(Matrix);

	Matrix operator+(Matrix);
	Matrix operator-(Matrix);
	Matrix operator*(double);
	Matrix operator*(Matrix);

	//function functions
	Matrix &trans();

	Matrix &exchange2Rows(unsigned int row1,unsigned int row2);
	Matrix &kTimesPlusRow(unsigned int rowToMul, double times, unsigned int rowToPlus = 0);
	Matrix &exchange2Cols(unsigned int col1, unsigned int col2);
	Matrix &kTimesPlusCol(unsigned int colToMul, double times, unsigned int colToPlus = 0);

	Matrix &toUpTriangleForm(bool *isExchange = NULL, bool isShowProcess = false);

	double det(bool isShowProcess = false);
	unsigned int rank(bool isShowProcess = false);

	double cofactor(unsigned int row, unsigned int col, bool isShowProcess = false);
	Matrix adjoint(bool isShowProcess = false);

	Matrix inverse(bool isShowProcess = false);

	//deconstruct function
	~Matrix();

protected:
	double **mat;  //data of the matrix
	unsigned int rows, cols; //rows and cols of the matrix
};

//math operator reload
Matrix operator*(double, Matrix);

//IO operator reload
std::ostream &operator<<(std::ostream &os, Matrix&);
std::istream &operator>>(std::istream &is, Matrix&);

//inline functions

/***************************************************/
//Func:Matrix::getVal
//Para:unsigned int  row	row of the object element
//	   unsigned int  col	col of the object element
//Retn:double        elev   value of the object element
//Objt:get value of certain element
/***************************************************/
//get value of certain element
double Matrix::getVal(unsigned int row, unsigned int col)
{
	return mat[row-1][col-1];
}

/***************************************************/
//Func:Matrix::getRow
//Para:none
//Retn:unsigned int	row		rows of the matrix
//Objt:get rows of the matrix
/***************************************************/
//get rows of the matrix
unsigned int Matrix::getRow()
{
	return rows;
}

/***************************************************/
//Func:Matrix::getCol
//Para:none
//Retn:unsigned int	col		cols of the matrix
//Objt:get columns of the matrix
/***************************************************/
//get columns of the matrix
unsigned int Matrix::getCol()
{
	return cols;
}

//inline functions end